package utils

import (
	"bytes"
	"crypto/md5"
	"crypto/sha1"
	"encoding/json"
	"gitee.com/z930255076/go-ext/constants"
	"github.com/bwmarrin/snowflake"
	"github.com/gofiber/fiber/v2"
	"io"
	"math/rand"
	"net/http"
	"os"
	"strconv"
	"time"
)

// Token 生成token
func Token() string {
	salt := RandomString(8)
	timeStr := strconv.Itoa(int(time.Now().Unix() * 1000))
	md5 := md5.New()
	md5.Write([]byte(timeStr))
	appID, _ := strconv.Atoi(os.Getenv("APP_ID"))
	node, _ := snowflake.NewNode(int64(appID))
	snowflakeStr := strconv.Itoa(int(node.Generate()))
	hash := sha1.New()
	resultStr := snowflakeStr + timeStr + salt
	hash.Write([]byte(resultStr))

	return resultStr
}

// RandomString 生成随机字符串
func RandomString(length int) string {
	var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
	stringData := make([]rune, length)
	for i := range stringData {
		stringData[i] = letters[rand.Intn(len(letters))]
	}

	return string(stringData)
}

func GetEnv(key string, defaultValue ...string) string {
	if value, ok := os.LookupEnv(key); ok {
		return value
	}

	if len(defaultValue) > 0 {
		return defaultValue[0]
	}

	return ""
}

func Request(params interface{}, method string, url string, headers map[string]string, result interface{}) error {
	// 将参数转换为JSON
	jsonStr, _ := json.Marshal(params)
	requestBody := bytes.NewBuffer(jsonStr)

	// 创建请求对象，指定方法、URL和请求体
	req, err := http.NewRequest(method, url, requestBody)
	if err != nil {
		return fiber.NewError(constants.NormalError, "创建请求对象错误")
	}

	// 设置请求头
	for k, v := range headers {
		req.Header.Set(k, v)
	}

	// 创建客户端对象并发送请求
	client := &http.Client{}
	beforeTime := time.Now()
	res, err := client.Do(req)
	if err != nil {
		return fiber.NewError(constants.NormalError, "发送请求错误")
	}

	defer res.Body.Close()
	body, err := io.ReadAll(res.Body)
	if err != nil {
		return fiber.NewError(constants.NormalError, "读取回传数据错误")
	}

	err = json.Unmarshal(body, result)
	if err != nil {
		return fiber.NewError(constants.NormalError, "解析回传数据错误")
	}

	httpData := Http{
		Runtime: time.Now().Sub(beforeTime).String(),
		Header:  headers,
		Params:  params,
		Result:  string(body),
	}
	err = json.Unmarshal(body, &httpData.Result)
	if err != nil {
		return fiber.NewError(constants.NormalError, "解析回传数据到debug错误")
	}

	defer TE.SetAnHttp(httpData)

	return nil
}

func StructToTree(structData interface{}, pID int64, pIDField string, pkField string, childrenName string, level int64) []map[string]interface{} {
	jsonData, err := json.Marshal(structData)
	var treeData []map[string]interface{}
	if err != nil {
		return treeData
	}

	typeMap := make([]map[string]interface{}, 0)
	err = json.Unmarshal(jsonData, &typeMap)
	if err != nil {
		return treeData
	}

	return ListToTree(typeMap, pID, pIDField, pkField, childrenName, level)
}

func ListToTree(list []map[string]interface{}, pID int64, pIDField string, pkField string, childrenName string, level int64) []map[string]interface{} {
	var treeData []map[string]interface{}
	data := make(map[string]interface{})
	for _, v := range list {
		vPID, _ := v[pIDField].(float64)
		vID, _ := v[pkField].(float64)
		if int64(vPID) == pID {
			data = v
			data["level"] = level + 1
			data[childrenName] = ListToTree(list, int64(vID), pIDField, pkField, childrenName, level+1)
			treeData = append(treeData, data)
		}
	}

	return treeData
}
